import React, { useRef, useState } from 'react'
import axios from 'axios'
import sparkMD5 from 'spark-md5'
const CHUNK_SIZE = 5 * 1024 * 1024
export default function Home() {
    const [file, setFile] = useState(null)//用于存储用户选择的文件
    const [uploadProgress, setUploadProgress] = useState(0)//用于存储上传进度
    const uploading = useRef(false)//用于防止重复出发上传逻辑
    //当用户选择文件时触发
    const handleFileChange = (e) => {
        setFile(e.target.files[0])//将用户选择的文件存储到state中
        setUploadProgress(0)//将上传进度重置为0
    }
    //计算文件的唯一标识(哈希)
    const calculateHash = async (file) => {
        return new Promise(resolve => {
            const reader = new FileReader()
            reader.onload = (e) => {
                const hash = sparkMD5.ArrayBuffer.hash(e.target.result)
                resolve(hash)
            }
            reader.readAsArrayBuffer(file)
        })
    }
    //开始文件上传
    const handleUpload = async () => {
        if (!file || uploading.current) return
        ///如果未选择文件或正在上传，则直接返回
        uploading.current = true//标记为正在上传
        const fileHash = await calculateHash(file)//计算文件的哈希值
        console.log(`fileHash:${fileHash}`);
        const totalChunks = Math.ceil(file.size / CHUNK_SIZE)//计算文件的总块数
        //检查哪些分片已经上传
        const { data: uploadedChunks } = await axios.post('http://localhost:3000/check', {
            fileName: file.name,
            fileHash
        })
        //上传未完成的分片
        for (let i = 0; i < totalChunks; i++) {
            if (uploadedChunks.includes(i)) {
                console.log(`分片${i}已经上传`);
                setUploadProgress((i + 1) / totalChunks * 100)//更新进度
            }//如果分片已经上传，则跳过
            console.log(`开始上传分片${i}`);
            //创建当前分片
            const start = i * CHUNK_SIZE;//计算当前分片的起始位置
            const end = Math.min(file.size, start + CHUNK_SIZE);//计算当前分片的结束位置
            const chunk = file.slice(start, end);//从文件中截取当前分片
            //上传分片
            const formData = new FormData()
            formData.append('chunk', chunk)//当前分片
            formData.append('fileName', file.name)//文件名
            formData.append('fileHash', fileHash)//文件哈希值
            formData.append('chunkIndex', i)//当前分片索引
            await axios.post(`http://localhost:3000/upload?fileHash=${fileHash}&chunkIndex=${i}`), formData, {
                onUploadProgress: (progressEvent) => {
                    setUploadProgress((i + 1) / totalChunks * 100)//更新进度
                }
                //通知服务器端合并分片
            }
        }
        //通知服务器断合并分片
        await axios.post(`http://localhost:3000/merge`, {
            fileHash,
            fileName: file.name,
            totalChunks
        })
        alert('上传完成')
        //标记上传成功
        uploading.current = false
    }

    return (
        <div>
            <p>大文件上传(支持断点续传)</p>
            <input type="file" onChange={handleFileChange} />
            <button onClick={handleUpload}>上传</button>
            <div style={{ marginTop: '20px' }}>
                <progress value={uploadProgress} max="100"></progress>
                <p>上传进度：{uploadProgress.toFixed(2)}%</p>
            </div>
        </div>
    )
}
